package com.hydra.auth.service.impl;

import com.hydra.auth.common.AuthConstant;
import com.hydra.base.auth.UserRoleEnum;
import com.hydra.auth.dto.LoginDto;
import com.hydra.auth.dto.TokenDto;
import com.hydra.auth.entity.SysRole;
import com.hydra.auth.entity.SysUser;
import com.hydra.auth.service.AuthService;
import com.hydra.auth.service.LoginService;
import com.hydra.auth.utils.AesEncryptUtil;
//import com.hydra.auth.utils.JwtTokenUtil;
import com.hydra.base.common.Constant;
import com.hydra.base.error.BusinessException;
import com.hydra.base.error.ValidateException;
import com.hydra.base.redis.RedisPlugin;
import com.hydra.base.utils.CommonUtil;
import com.hydra.base.utils.FormatUtil;
import com.hydra.base.utils.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import java.util.Collections;
import java.util.List;

import static com.hydra.auth.common.AuthConstant.RegisterConstant.*;

/**
 * 用户接口实现类
 * @Author Hydra
 * @Date 2022/5/27 13:27
 */
@Slf4j
@Service
public class AuthServiceImpl implements AuthService {

    @Resource
    private MailValidateCodeServiceImpl mailValidateCodeServiceImpl;

    @Resource
    private LoginService loginService;

    @Resource
    private AuthenticationManager authenticationManager;

    @Resource
    private RedisPlugin redisPlugin;

//    @Override
//    public TokenDto login(LoginDto user) {
//        String username = CommonUtil.requireNonNull(user.getUsername(), "用户名");
//        String password = CommonUtil.requireNonNull(user.getPassword(), "密码");
//
//        //验证登录
//        Authentication authenticate = this.authenticate(username, password);
//        if(authenticate == null){
//            throw new BusinessException("登录失败！");
//        }
//        //获取用户
//        SysUser principal = (SysUser)authenticate.getPrincipal();
//        return this.generateToken(principal);
//    }
//
//    @Override
//    public TokenDto temporaryLogin(temporaryLogin.Input input) {
//        //构建临时用户，登录
//        SysUser user = this.generateTemporaryUser(input.getCode());
//        return this.generateToken(user);
//    }
//
//    /**
//     * 构建token对象
//     * @param user  用户信息
//     * @return  token结果
//     */
//    private TokenDto generateToken(SysUser user){
//        //生成token
//        String token = "";//JwtTokenUtil.generateToken(user);
//        //保存到redis中
//        redisPlugin.setObject(Constant.REDIS_KEY_LOGIN_TOKEN_PREFIX + token, user, Constant.JWT_TOKEN_VALIDITY);
//
//        //返回结果集
//        TokenDto dto = new TokenDto();
//        dto.setToken(token);
//        return dto;
//    }

    /**
     * 忘记密码
     */
    @Override
    public forgetPassword.Output forgetPassword(forgetPassword.Input input) {
        forgetPassword.Output output = new forgetPassword.Output();
        String type = FormatUtil.isNullToString(input.getType(), FORGET_PASSWORD_TYPE_MAIL);
        if(FORGET_PASSWORD_TYPE_MAIL.equals(type)){
            //通过邮件找回密码
            String target = input.getTarget();

            boolean validate = mailValidateCodeServiceImpl.validate(target, VALIDATE_CODE_TYPE_FORGET_PASSWORD, input.getCode());
            if(!validate){
                throw new BusinessException("验证码错误，请检查后重试！");
            }
            //判断用户名是否存在
            String password = CommonUtil.requireNonNull(input.getPassword(), "密码");
            String passwordAgain = CommonUtil.requireNonNull(input.getPasswordAgain(), "密码");
            if(!password.equals(passwordAgain)){
                throw new ValidateException("两次密码不一致！");
            }

            //判断邮箱是否存在
            SysUser user = loginService.findByEmail(target);
            if(user == null){
                throw new BusinessException("账户不存在，请检查后重试！");
            }
            //开始修改密码
            loginService.modifyPassword(user, password);
            output.setResult(true);
            output.setMessage("密码修改成功");
        }
        return output;
    }

    /**生成临时用户*/
    public SysUser generateTemporaryUser(String code){
        PasswordEncoder passwordEncoder = SpringUtils.getBean(PasswordEncoder.class);
        //构建密码
        String encodePassword = passwordEncoder.encode(AuthConstant.TEMPORARY_USER_PASSWORD);
        //创建临时用户
        SysUser user = new SysUser();
        user.initEntity();
        user.setCode(code);
        user.setName("临时用户"+code)
                .setUsername("temporary_"+code)
                .setPassword(encodePassword)
                .setStatus(AuthConstant.USER_STATUS_ON);
        //获取角色
        SysRole role = new SysRole()
                .setRoleName("临时用户")
                .setRoleCode(UserRoleEnum.ROLE_TEMPORARY_USER.getCode())
                .setStatus(AuthConstant.ROLE_STATUS_ON);
        List<SysRole> roles = Collections.singletonList(role);
        user.setRoles(roles);
        //判断是否保存临时用户
        return user;
    }


    /**
     * 授权校验
     */
    private Authentication authenticate(String username, String password) {
        CommonUtil.requireNonNull(username, "用户名");
        CommonUtil.requireNonNull(password, "密码");
        try {
            //做一次解密
            password = AesEncryptUtil.decrypt(password);
            //调用security登录验证
            return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
        } catch (DisabledException e) {
            log.error(e.getMessage());
            throw new BusinessException("用户已被禁用！");
        } catch (BadCredentialsException e) {
            log.error(e.getMessage());
            throw new BusinessException("账号或者密码错误！");
        }
    }

}
